// --------------------------------------------------------------------------------------------------------------------
// <copyright file="AudioRecord.cs" company="3po.ru">
//   Alexander Ulitin [support@3po.ru]
// </copyright>
// <summary>
//   Realization of one Audio object
// </summary>
// --------------------------------------------------------------------------------------------------------------------
namespace Conusic
{
    using System.Collections.Generic;
    using System.IO;

    using Conusic.Properties;

    /// <summary>
    ///   Realization of one Audio object
    /// </summary>
    public sealed class AudioRecord
    {
        #region Static Fields

        /// <summary>
        /// The invalid chars filename.
        /// </summary>
        private static readonly Dictionary<char, bool> invalidCharsFilename = GetInvalidFileNameCharsDictionary();

        #endregion

        #region Constructors and Destructors

        /// <summary>
        /// Initializes a new instance of the <see cref="AudioRecord"/> class.
        /// </summary>
        public AudioRecord()
        {
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AudioRecord"/> class.
        /// </summary>
        /// <param name="artist">
        /// The artist.
        /// </param>
        /// <param name="compositionName">
        /// The composition name.
        /// </param>
        public AudioRecord(string artist, string compositionName)
        {
            this.Artist = artist;
            this.CompositionName = compositionName;
        }

        /// <summary>
        /// Initializes a new instance of the <see cref="AudioRecord"/> class.
        /// </summary>
        /// <param name="url">
        /// The url.
        /// </param>
        /// <param name="duration">
        /// The duration.
        /// </param>
        /// <param name="compositionName">
        /// The composition name.
        /// </param>
        /// <param name="artist">
        /// The artist.
        /// </param>
        public AudioRecord(string artist, string compositionName, int duration, string url)
        {
            this.Url = url;
            this.Duration = duration;
            this.CompositionName = compositionName;
            this.Artist = artist;
        }

        #endregion

        #region Public Properties

        /// <summary>
        /// Gets or sets the artist.
        /// </summary>
        public string Artist { get; set; }

        /// <summary>
        ///   Gets the concat of artist and composition.
        /// </summary>
        public string ArtistAndComposition
        {
            get
            {
                return this.Artist + " " + this.CompositionName;
            }
        }

        /// <summary>
        /// Gets or sets the composition name.
        /// </summary>
        public string CompositionName { get; set; }

        /// <summary>
        ///   Duration in seconds.
        /// </summary>
        public int Duration { get; set; }

        /// <summary>
        ///   Gets the duration in format Minutes:second.
        /// </summary>
        public string DurationMs
        {
            get
            {
                return string.Format("{0}:{1:D2}", this.Duration / 60, this.Duration % 60);
            }
        }

        /// <summary>
        ///   Correct filename path to song.
        /// </summary>
        public string Filename
        {
            get
            {
                string filename = this.Artist + " - " + this.CompositionName + ".mp3";
                return EscapeFilename(filename);
            }
        }

        /// <summary>
        /// Gets unique full filename.
        /// </summary>
        public string GetFullFilename()
        {
            string currentFileName = this.Filename;
            var filename = string.Format(
                "{0}{1}{2}", Settings.Default.DownloadDirectory, Path.DirectorySeparatorChar, currentFileName);
            int i = 1;
            while (File.Exists(filename))
            {
                filename = string.Format(
                    "{0}{1}{2}_{3}.{4}",
                    Settings.Default.DownloadDirectory,
                    Path.DirectorySeparatorChar,
                    Path.GetFileNameWithoutExtension(currentFileName),
                    i,
                    Path.GetExtension(currentFileName));
                i++;
            }

            return filename;
        }

        /// <summary>
        /// Gets or sets the url.
        /// </summary>
        public string Url { get; set; }

        /// <summary>
        /// Gets or sets the vkontakte lyric id.
        /// </summary>
        public int VkontakteLyricId { get; set; }

        #endregion

        #region Public Methods and Operators

        /// <summary>
        /// Escapes the filename.
        /// </summary>
        /// <param name="filename">
        /// The filename.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string EscapeFilename(string filename)
        {
            for (int i = 0; i < filename.Length; i++)
            {
                if (invalidCharsFilename.ContainsKey(filename[i]))
                {
                    filename = filename.Remove(i, 1);
                    if (i >= 0)
                    {
                        i--;
                    }
                }
            }

            return filename;
        }

        /// <summary>
        /// The json escape.
        /// </summary>
        /// <param name="input">
        /// The input.
        /// </param>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public static string JsonEscape(string input)
        {
            input = input.Replace("\\", "\\\\");
            input = input.Replace("\"", "\\\"");
            return input;
        }

        /// <summary>
        /// The json.
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public string Json()
        {
            // {"name" : "name", "artist" : "artist", "duration":duration, "url":"url","lid":lid}
            return
                string.Format(
                    "{{\"name\" : \"{0}\", \"artist\" : \"{1}\", \"duration\":{2}, \"url\":\"{3}\",\"lid\":{4}}}", 
                    JsonEscape(this.CompositionName), 
                    JsonEscape(this.Artist), 
                    this.Duration, 
                    JsonEscape(this.Url), 
                    this.VkontakteLyricId);
        }

        /// <summary>
        /// The to string.
        /// </summary>
        /// <returns>
        /// The <see cref="string"/>.
        /// </returns>
        public override string ToString()
        {
            return this.ArtistAndComposition;
        }

        #endregion

        #region Methods

        /// <summary>
        /// Implement ToDictionary in .net 3.5
        /// </summary>
        /// <returns>
        /// The <see cref="Dictionary"/>.
        /// </returns>
        private static Dictionary<char, bool> GetInvalidFileNameCharsDictionary()
        {
            var result = new Dictionary<char, bool>();
            char[] invalidChars = Path.GetInvalidFileNameChars();
            foreach (char invalidChar in invalidChars)
            {
                result.Add(invalidChar, true);
            }

            return result;
        }

        #endregion
    }
}